import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:device_info/device_info.dart';
import 'package:dio/dio.dart';
import 'package:dio_log/interceptor/dio_log_interceptor.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_network/toast.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/route_manager.dart';
import 'package:uuid/uuid.dart';
import 'package:wallet_utils/event_bus_utils.dart';
import 'package:wallet_utils/log_util.dart';
import 'package:wallet_utils/login_utils.dart';
import 'package:wallet_utils/msg_event_utils.dart';
import 'package:wallet_utils/vrShow.dart';
import 'package:package_info/package_info.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http_parser/http_parser.dart';
import 'log_cache_interceptor.dart';
import 'netwrokstatus.dart';
import 'oss/oss_utils.dart';

///网络框架
class HttpRequest {
  static CancelToken? token;
  late DeviceInfoPlugin deviceInfo;
  late PackageInfo packageInfo;
  late SharedPreferences prfs;

  Future initDio(url, {String? requestName}) async {
    token = CancelToken();
    deviceInfo = DeviceInfoPlugin(); //获取设备信息
    packageInfo = await PackageInfo.fromPlatform(); //获取app应用信息
    prfs = await SharedPreferences.getInstance();
    Uuid uuid = const Uuid();
    String uuidStr = uuid.v4();
    Dio dio = new Dio();
    dio.interceptors.add(LogInterceptor(responseBody: true));
    dio.interceptors
      ..add(LogCacheInterceptor(requestName: requestName))
      ..add(LogInterceptor(
          responseBody: true,
          logPrint: (text) {
            //只有debug包打印log
            if (!bool.fromEnvironment("dart.vm.product")) {
              log('┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭┭ :$text');
            }
          }))
      ..add(DioLogInterceptor()) //log抓包工具
      ..add(InterceptorsWrapper(onRequest: (RequestOptions option, RequestInterceptorHandler handler) async {
        option.headers["appVersion"] = packageInfo.version;
        option.headers["Authorization"] = await LoginUtils.getAuthorization() ?? '';
        option.headers["Accept"] = "application/json";

        // option.headers["channel"] = "ALL_ONLINE";
        option.headers["rolePId"] = "";
        if (Platform.isAndroid) {
          AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
          option.headers["channel"] = "ANDROID";
          option.headers["osVersion"] = androidInfo.brand;
          option.headers["deviceModel"] = androidInfo.product;
          option.headers["deviceBrand"] = androidInfo.brand;
        } else {
          IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
          option.headers["osVersion"] = iosInfo.name;
          option.headers["deviceModel"] = iosInfo.model;
//           option.headers["deviceBrand"] = iosInfo.brand;
          option.headers["channel"] = "IOS";
        }
        option.headers["uuid"] = DateTime.now().millisecondsSinceEpoch.toString() + uuidStr.substring(0, 5);
        option.headers["unDecode"] = "1";

        LogUtils.d("headers  params=========> :${option.headers.toString()}");
        handler.next(option);
      }));
    return dio;
  }

  //封装网络请求Post
  requestPost(url,
      {Map<dynamic, dynamic>? pathParams,
      Map<String, dynamic>? queryParams,
      Map<dynamic, dynamic>? params,
      String? requestName,
      dynamic data, //可以传数组
      List<Map<dynamic, dynamic>>? listParams,
      CancelToken? cancelToken,
      Map<String, dynamic>? headers,
      Map<String, dynamic>? formData}) async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      flutterToast(msg: "请查看您的网络连接");
    } else {
      LogUtils.d("POST request params=========>${url}\n${json.encode(params)}");
      // LogUtils.d("POST request params=========> ${formData}");
      //LogUtils.d("POST request params=========>}");
      LogUtils.d("POST request params=========> $listParams");
      LogUtils.d("POST request params=========> ${formData}");
      if (formData == null || formData.length == 0) {
        return await request(url, Options(method: 'POST', responseType: ResponseType.json, headers: headers),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      } else {
        return await request(url, Options(method: 'POST', responseType: ResponseType.json, headers: headers),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            formData: FormData.fromMap(formData),
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      }
    }
  }

  //封装put请求方式
  requestPut(url,
      {Map<dynamic, dynamic>? pathParams,
      Map<String, dynamic>? queryParams,
      Map<dynamic, dynamic>? params,
      String? requestName,
      dynamic data, //可以传数组
      List<Map<dynamic, dynamic>>? listParams,
      CancelToken? cancelToken,
      Map<String, dynamic>? formData}) async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      flutterToast(msg: "请查看您的网络连接");
    } else {
      LogUtils.d("PUT request params=========> $params");
      LogUtils.d("PUT request params=========> ${formData}");
      if (formData == null || formData.length == 0) {
        return await request(url, Options(method: 'PUT', responseType: ResponseType.json),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      } else {
        return await request(url, Options(method: 'PUT', responseType: ResponseType.json),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            formData: FormData.fromMap(formData),
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      }
    }
  }

  //封装DELETE请求方式
  requestDelete(url,
      {Map<dynamic, dynamic>? pathParams,
      Map<String, dynamic>? queryParams,
      Map<dynamic, dynamic>? params,
      String? requestName,
      dynamic data, //可以传数组
      List<Map<dynamic, dynamic>>? listParams,
      CancelToken? cancelToken,
      Map<String, dynamic>? formData}) async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      flutterToast(msg: "请查看您的网络连接");
    } else {
      LogUtils.d("DELETE request params=========> $params");
      LogUtils.d("DELETE request params=========> ${formData}");
      if (formData == null || formData.length == 0) {
        return await request(url, Options(method: 'DELETE', responseType: ResponseType.json),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      } else {
        return await request(url, Options(method: 'DELETE', responseType: ResponseType.json),
            pathParams: pathParams,
            queryParameters: queryParams,
            postParams: params,
            data: data,
            formData: FormData.fromMap(formData),
            listParams: listParams,
            requestName: requestName,
            cancelToken: cancelToken);
      }
    }
  }

  //上传图片请求
  uploadImgFormToken(url, {Map<String, dynamic>? params}) async {
    FormData formData = FormData.fromMap(params!);
    ContentType.parse("application/octet-stream");
    return request(url, Options(method: 'POST'), formData: formData, requestName: "七牛上传图片不进入统计");
  }

  base64(url) async {
    return request(url, Options(method: 'GET', responseType: ResponseType.bytes), requestName: 'base64');
  }

  updateFile(imagePath, url) async {
    String path = imagePath.path;
    ImageFormat imageFormat = ImageFormatExtension.getFormat(path);
    var name = path.substring(path.lastIndexOf("/") + 1, path.length);
    FormData formdata = FormData.fromMap(
      {"file": await MultipartFile.fromFile(path, filename: name, contentType: MediaType('image', imageFormat.getSuffix()))},
    );
    return request(
        url,
        Options(
          contentType: 'multipart/form-data',
          responseType: ResponseType.plain,
          method: 'POST',
        ),
        formData: formdata);
  }

//封装网络请求Get
  requestGet(
    url, {
    Map<String, dynamic>? params,
    String? requestName,
    Map<String, dynamic>? formData,
    Map<String, dynamic>? headers,
    CancelToken? cancelToken,
  }) async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      flutterToast(msg: "请查看您的网络连接");
    } else {
      LogUtils.d("GET request params=========> $params");
      if (formData == null || formData.length == 0) {
        return await request(url, Options(method: 'GET' ,headers: headers),
            queryParameters: params, requestName: requestName, cancelToken: cancelToken);
      } else {
        return await request(url, Options(method: 'GET', headers: headers),
            queryParameters: params, formData: FormData.fromMap(formData), requestName: requestName, cancelToken: cancelToken);
      }
    }
  }

  //封装网络请求Get path请求
  requestGetPath(url, {Map<dynamic, dynamic>? pathParams, Map<String, dynamic>? queryParams, String? requestName}) async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      flutterToast(msg: "请查看您的网络连接");
    } else {
      return await request(url, Options(method: 'GET'),
          pathParams: pathParams, queryParameters: queryParams, requestName: requestName);
    }
  }

  //最终请求网络方法
  request(
    url,
    Options option, {
    Map<dynamic, dynamic>? postParams,
    Map<dynamic, dynamic>? pathParams,
    Map<String, dynamic>? queryParameters,
    FormData? formData,
    dynamic data,
    List<Map<dynamic, dynamic>>? listParams,
    String? requestName,
    CancelToken? cancelToken,
  }) async {
    Response response;
    Dio dio = await initDio(url, requestName: requestName);

    ///先添加path路径
    if (pathParams != null) {
      pathParams.keys.forEach((key) {
        url = url + "/${pathParams[key]}";
      });
    }

    ///添加公共参数
    // url = await appendPublicParams(
    //   url,
    //   deviceInfo: deviceInfo,
    //   packageInfo: packageInfo,
    //   prfs: prfs,
    // );

    try {
      response = await dio.request(url,
          data: data ?? formData ?? postParams ?? listParams,
          queryParameters: queryParameters,
          options: option,
          cancelToken: cancelToken ?? null);

      if (requestName == 'base64') {
        if (response.statusCode == 200) {
          return response.data;
        }
      } else {
        late Map<String, dynamic> res;
        try {
          res = json.decode(response.toString());
          if (response.statusCode == 200 &&
              res['code'] != 203 &&
              res['code'] != 403 &&
              res['code'] != 2002 &&
              res['code'] != 2004 &&
              res['code'] != 2005) {
            return response;
          } else if (res['code'] == 203 || res['code'] == 403 || res['code'] == 2002) {
            //token鉴权失效
            tokenFail(res['msg']);
            res['msg'] = '';
            response = Response(data: res, requestOptions: RequestOptions(path: 'www.hopsontone.com'));
            return response;
          } else if (res['code'] == 2004) {
            //权限失效 无权访问
            tokenFail(res['msg']);
            res['msg'] = '';
            response = Response(data: res, requestOptions: RequestOptions(path: 'hopsontone'));
            return response;
          } else if (res['code'] == 2005) {
            //另一台设备登录
            tokenFail(res['msg']);
            res['msg'] = '';
            response = Response(data: res, requestOptions: RequestOptions(path: 'hopsontone'));
            return response;
          } else {
            throw Exception("接口异常");
          }
        } catch (e) {
          throw Exception("接口数据转换异常");
        }
      }
    } on DioError catch (e) {
      // 请求错误处理
      if (e.response != null) {
        response = e.response!;
      } else {
        //这里手动创建一个Response,用于定位是因为什么导致的失败
        response = Response<Map<String, dynamic>>(statusCode: 666, data: {}, requestOptions: RequestOptions(path: "hopsontone"));
      }
      if (e.type == DioErrorType.connectTimeout) {
        flutterToast(msg: "请求超时");
      }
      if (e.type == DioErrorType.cancel) {
        //取消请求code值定义
        response.statusCode = -999;
      }
      LogUtils.d('请求异常========>:' + e.toString());
      LogUtils.d('请求异常=======> url: ' + url);
      return response;
    }
  }

  //token失效
  static void tokenFail(String msg) {
    isLogin().then((value) => EventBusUtils.getInstance().fire(MsgEventBusUtils(203, value: msg)));
    /*登录失效,注销vr监听*/
    VRShowManager.vrsDKLoginOut();
  }

  //无权访问
  static void permissionFail(msg) {
    showCupertinoDialog(
        context: Get.context!,
        builder: (context) {
          return CupertinoAlertDialog(
            title: Text('提示'),
            content: Column(
              children: <Widget>[
                SizedBox(
                  height: 20.w,
                ),
                Align(
                  child: Text(msg),
                  alignment: Alignment.center,
                ),
              ],
            ),
            actions: <Widget>[
              CupertinoButton(
                child: Text("确定"),
                onPressed: () {
                  Navigator.pop(context);
                  // Navigator.pop(context);
                },
              ),
            ],
          );
        });
  }

  ///抛异常
  static errorResponse(e) {
    Response response = Response(requestOptions: RequestOptions(path: ""));
    response.data = "{}";
    response.statusCode = 6667;
    response.statusMessage = "${e.toString()}";
  }

  Future appendPublicParams(String url,
      {SharedPreferences? prfs, required DeviceInfoPlugin deviceInfo, required PackageInfo packageInfo}) async {
    String netWorkStatus = "LTE";
    if (await NetWifiStatusUtil.isWifi()) {
      netWorkStatus = "wifi";
    }
    url = url.appendURL(value: packageInfo.version, key: "v");
    url = url.appendURL(value: prfs!.getString("marketId") ?? "218", key: "marketId");
    url = url.appendURL(value: prfs.getString("marketId") ?? "218", key: "marketid");
    url = url.appendURL(value: netWorkStatus, key: "net");
    url = url.appendURL(value: prfs.getString("marketId") ?? "", key: "cid");
    url = url.appendURL(value: "2", key: "channel");
    url = url.appendURL(value: "HopsonTong-B", key: "appid");
    url = url.appendURL(value: prfs.getString("businessId"), key: "businessId");
    url = url.appendURL(value: prfs.getString("roleId"), key: "roleId");
    url = url.appendURL(value: prfs.getString("businessLoginId"), key: "businessLoginId");
    // url = url.appendURL(value: prfs.getString("shopType"), key: "shopType");
    if (Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      url = url.appendURL(value: "tencent", key: "b");
      url = url.appendURL(value: androidInfo.brand, key: "m"); //手机品牌
      url = url.appendURL(value: "app", key: "from");
      url = url.appendURL(value: "android", key: "os");
    } else {
      IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
      url = url.appendURL(value: "www.apple.com", key: "b");
      url = url.appendURL(value: iosDeviceInfo.name, key: "m"); //手机型号
      url = url.appendURL(value: "app", key: "from");
      url = url.appendURL(value: iosDeviceInfo.systemVersion, key: "os");
    }
    return url;
  }

  //判断是否登录
  static Future<bool> isLogin() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    String? loginStr = preferences.getString("loginBean");
    if (loginStr!.isEmpty) {
      return false;
    } else {
      return true;
    }
  }
}

extension URLFormatExtension on String {
  String appendURL({String? value, String? key}) {
    if (this.contains("${key}=")) {
      return this;
    }
    String item = "${key}=${value.toString()}";
    if (this.contains(item)) {
      return this;
    }
    String temp = this;
    temp = temp.appendConnector();
    temp = temp + item;
    return temp;
  }

  String appendConnector() {
    if (!this.contains('?')) {
      return this + "?";
    } else {
      return this + "&";
    }
  }

  ///添加双向认证证书
/* addCertificate(Dio _dio) async {
    ByteData data =
        await rootBundle.load('assets/certificate/[certificateName].crt');
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      SecurityContext securityContext = new SecurityContext();
      securityContext.setTrustedCertificatesBytes(data.buffer.asUint8List());
      client = HttpClient(context: securityContext);
      return client;
    };
  }*/
}
